﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Microsoft.HomeServer.Extensibility;
using Microsoft.HomeServer.SDK.Interop.v1;
using Telerik.WinControls;
using Telerik.WinControls.UI;
using Umbrella.Whs.Contracts;

namespace Umbrella.Whs.WhsAddin
{
    [TabIdentifier(UmbrellaConsoleTab.TabId)]
    public partial class UmbrellaConsoleTab : UserControl, IConsoleTab
    {
        public const string TabId = "UmbrellaConsoleTab";

        private readonly log4net.ILog _log = log4net.LogManager.GetLogger(typeof(UmbrellaConsoleTab));
        private readonly IConsoleServices _services;
        private readonly WHSInfoClass _whsInfo;
        private readonly SingletonServiceFactory _singletonService = new SingletonServiceFactory();

        public IConsoleServices Services
        {
            get { return _services; }
        }

        public UmbrellaConsoleTab(int width, int height, IConsoleServices consoleServices)
        {
            // init
            InitializeComponent();

            // hook
            this.Size = new Size(width, height);
            _services = consoleServices;
            _whsInfo = new WHSInfoClass();
            _whsInfo.Init(Whs.Properties.Constants.ApplicationName);

            // receive state transitions
            AddinStateManager.Instance.OnStateChanging += SetState;
        }

        public bool GetHelp()
        {
            return false;
        }

        public Guid SettingsGuid
        {
            get { return UmbrellaSettingsTab.SettingsTabGuid; }
        }

        public Control TabControl
        {
            get { return this; }
        }

        public Bitmap TabImage
        {
            get { return Properties.Resources.imgTabLogo; }
        }

        public string TabText
        {
            get { return Properties.Resources.txtConsoleTabTitle; }
        }

        private void checkUpdateAvailableTimer_Tick(object sender, EventArgs e)
        {
            try
            {
                if (_singletonService.IsWindowsServiceRunning() != SingletonServiceFactory.ServiceStatus.Running)
                    return;

                // update status
                var newVersion = _singletonService.Channel.GetNewerVersion();

                if (newVersion == null)
                {
                    // remove tab
                    EnsureTabRemoved<ConsoleTabControls.UpdateAvailable>();
                }
                else
                {
                    var tab = EnsureTabAdded(
                        () => new ConsoleTabControls.UpdateAvailable(this)
                        );

                    tab.ToolTipText = string.Format(
                        Properties.Resources.txtUpdateAvailableButtonTooltip,
                        newVersion.VersionString
                        );
                }
            }
            catch (Exception ex)
            {
                _log.Error("Failed to update update status", ex);
            }
        }

        private void SetState(object sender, AddinStateTransitionEventArgs args)
        {
            // log
            if (_log.IsDebugEnabled)
                _log.Debug("Changing state start: " + args.Previous + " to " + args.Next);

            // change state
            try
            {
                this.SuspendLayout();

                // change state
                switch (args.Next)
                {
                    case AddinState.WindowsServiceNotRunning:
                    case AddinState.ConnectingToSharePoint:
                    case AddinState.SharePointNotInstalled:
                    case AddinState.SharePointNotUmbrella:
                        EnsureTabRemoved<ConsoleTabControls.Overview>();
                        EnsureTabRemoved<ConsoleTabControls.Users>();

                        EnsureTabAdded(() => new ConsoleTabControls.Startup(this));

                        break;

                    case AddinState.Ready:
                        EnsureTabRemoved<ConsoleTabControls.Startup>();

                        EnsureTabAdded(() => new ConsoleTabControls.Overview(this));
                        EnsureTabAdded(() => new ConsoleTabControls.Users(this));

                        break;

                    default:
                        _log.Error("state is not valid for console screen: " + args.Next);
                        break;
                }

                this.ResumeLayout();

                // log
                if (_log.IsDebugEnabled)
                    _log.Debug("Changing state done: " + args.Next);
            }
            catch (Exception ex)
            {
                _log.Fatal("Failed to change state from " + args.Previous + " to " + args.Next, ex);

                throw;
            }
        }

        public void ResetState()
        {
            try
            {
                if (_singletonService.IsWindowsServiceRunning() != SingletonServiceFactory.ServiceStatus.Running)
                    AddinStateManager.Instance.SetState(AddinState.WindowsServiceNotRunning);

                else
                    AddinStateManager.Instance.SetState(AddinState.ConnectingToSharePoint);

            }
            catch (Exception x)
            {
                _log.Fatal("Failed to reset state", x);

                throw;
            }
        }

        private void UmbrellaConsoleTab_Load(object sender, EventArgs e)
        {
            if (_log.IsDebugEnabled)
                _log.Debug("Loading start");

            try
            {
                // determine the default state
                ResetState();

                // done
                if (_log.IsDebugEnabled)
                    _log.Debug("Loading done");
            }
            catch (Exception ex)
            {
                _log.Fatal("Loading failed", ex);

                throw;
            }
        }

        public void OpenSettings()
        {
            try
            {
                _services.OpenSettings(UmbrellaSettingsTab.SettingsTabGuid);
            }
            catch (Exception x)
            {
                _log.Error("Failed to open settings", x);

                Microsoft.HomeServer.Controls.QMessageBox.Show(
                    x.Message,
                    Properties.Resources.txtOpenSettingsFailedTitle,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error
                    );
            }
        }

        private TabItem EnsureTabAdded<T>(Func<T> ctor) where T : ConsoleTabControls.ConsoleTabControlBase
        {
            if (ctor == null)
                throw new ArgumentNullException("ctor");

            var tt = typeof(T);

            // find the tab
            var tab = (
                from tb in this.radTabStrip.Items
                where tt == tb.Tag.GetType()
                select (TabItem)tb
                ).FirstOrDefault();

            // create new tab
            if (tab == null)
            {
                tab = ctor().CreateTabStripItem();

                // make sure the tag is set
                if (!(tab.Tag is ConsoleTabControls.ConsoleTabControlBase))
                {
                    throw new Exception("returned tab contains invalid Tag value");
                }

                // find right neighbour tab
                var rnbr = (
                    from tb in this.radTabStrip.Items
                    where ((ConsoleTabControls.ConsoleTabControlBase)tb.Tag).TabOrder >= ((ConsoleTabControls.ConsoleTabControlBase)tab.Tag).TabOrder
                    select tb
                    ).FirstOrDefault();

                // add to tab
                if (rnbr != null)
                {
                    this.radTabStrip.Items.Insert(this.radTabStrip.Items.IndexOf(rnbr), tab);
                }
                else
                {
                    this.radTabStrip.Items.Add(tab);
                }
            }

            // done
            return tab;
        }

        private void EnsureTabRemoved<T>() where T : ConsoleTabControls.ConsoleTabControlBase
        {
            var tt = typeof(T);

            // find the tab
            var tab = (
                from tb in this.radTabStrip.Items
                where tt == tb.Tag.GetType()
                select tb
                ).FirstOrDefault();

            // remove tab
            if (tab != null)
            {
                this.radTabStrip.Items.Remove(tab);

                tab.Dispose();
            }
        }

        private void checkServiceRunningTimer_Tick(object sender, EventArgs e)
        {
            try
            {
                // ensure the service is still running
                if ((AddinStateManager.Instance.State != AddinState.WindowsServiceNotRunning) &&
                    (_singletonService.IsWindowsServiceRunning() != SingletonServiceFactory.ServiceStatus.Running))
                {
                    ResetState();
                }
            }
            catch (Exception x)
            {
                _log.Error("Automatic check for service running failed", x);
            }
        }

    }
}


